package ar.com.temporis.framework.repository;

import java.util.Date;
import java.util.List;
import java.util.Random;

import org.apache.commons.lang.math.RandomUtils;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.criterion.Expression;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import ar.com.temporis.framework.domain.Entity;
import ar.com.temporis.framework.exception.ProgramException;


/**
 * 
 * @author matias.sulik
 * 
 */
public abstract class AbstractRepository extends HibernateDaoSupport implements
		Repository {

	@SuppressWarnings("unchecked")
	public List<? extends Entity> findAll() {
		return getHibernateTemplate().loadAll(getPersistedType());
	}

	@SuppressWarnings("unchecked")
	public List<Entity> findByAttribute(String attributeName, Object value) {
		return find(createCriteria().add(Expression.eq(attributeName, value)));
	}

	@SuppressWarnings("unchecked")
	public Entity getAny() {
		List list = this.createCriteria().setMaxResults(10).list();

		int index = 0;

		if (list.size() > 1) {
			index = RandomUtils.nextInt(new Random(new Date().getTime()), list.size());
		}
		
		return (Entity) list.get(index);
	}

	protected abstract Class<?> getPersistedType();

	@SuppressWarnings("unchecked")
	protected List<Entity> find(Criteria criteria) {
		try {
			return criteria.list();
		} catch (HibernateException e) {
			throw new ProgramException(e);
		}
	}

	protected Criteria createCriteria(Class<?> persistedType) {
		return getSession().createCriteria(persistedType);
	}

	public final Criteria createCriteria() {
		return createCriteria(getPersistedType());
	}
	
	public void add(Entity entity) {
		this.getHibernateTemplate().save(entity);
	}
	
	public void remove(Entity entity) {
		this.getHibernateTemplate().delete(entity);
	}
	
	public void update(Entity entity) {
		this.getHibernateTemplate().update(entity);
	}

}
